package com.muyu.danmo.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.muyu.common.core.constant.Constants;
import com.muyu.common.core.domain.Result;
import com.muyu.common.core.enums.OrderStatus;
import com.muyu.common.core.enums.PayStatus;
import com.muyu.danmo.mapper.DanmoOrderMapper;
import com.muyu.danmo.mapper.GoodsEvaluationInfoMapper;
import com.muyu.danmo.service.OrderFunctionService;
import com.muyu.danmo.utils.JPushUtils;
import com.muyu.system.danmo.dto.CloseDTO;
import com.muyu.system.danmo.dto.PaymentCallBackResult;
import com.muyu.system.danmo.dto.RefundDTO;
import com.muyu.system.danmo.fegin.PayFeign;
import com.muyu.system.danmo.vo.RefundResultVO;
import com.muyu.system.domain.DanmoOrder;
import com.muyu.system.domain.GoodsEvaluationInfo;
import com.muyu.system.domain.Vo.DanmoMarketOrderVO;
import com.muyu.system.domain.dto.*;
import com.muyu.system.domain.enums.JpushMessageEnum;
import com.muyu.system.domain.enums.OrderSourceEnum;
import com.muyu.system.domain.enums.ScoreTypeEnum;
import com.muyu.system.shopping.fegin.SecurityDepositFegin;
import kotlin.jvm.internal.Lambda;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.muyu.common.core.constant.CommonConstant.*;

/**
 * @author Administrator
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class OrderFunctionServiceImpl implements OrderFunctionService {


    private final PayFeign payFeign;

    private final DanmoOrderMapper danmoOrderMapper;

    private final GoodsEvaluationInfoMapper goodsEvaluationInfoMapper;

    private final JPushUtils jPushUtils;

    private final SecurityDepositFegin securityDepositFegin;

    @Value("${express.appCode}")
    private String appCode;

    /**
     * 快递查询
     */
    private final String url = "https://kzexpress.market.alicloudapi.com/api-mall/api/express/query";

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrder(CancelOrderDTO cancelOrderDTO) {
        String orderNo;
        // 获取订单信息
        if(cancelOrderDTO.getSource().equals(OrderSourceEnum.ORDER)){
            DanmoOrder danmoOrder = danmoOrderMapper.selectById(cancelOrderDTO.getOrderId());
            if(!danmoOrder.getStatus().equals(OrderStatus.PAY_PENDING)){
                throw new RuntimeException("订单状态异常");
            }
            orderNo = danmoOrder.getPayOrderNo();
        }else {
            Integer status = danmoOrderMapper.findMarketOrderStatusByPayId(cancelOrderDTO.getOrderId());
            OrderStatus orderStatus = OrderStatus.getByCode(status);
            if(!orderStatus.equals(OrderStatus.PAY_PENDING)){
                throw new RuntimeException("订单状态异常");
            }
            orderNo = danmoOrderMapper.findMarketOrderById(cancelOrderDTO.getOrderId());
        }
        if(StrUtil.isEmpty(orderNo)){
            throw new RuntimeException("订单号不存在");
        }
        CloseDTO closeDTO = new CloseDTO();
        closeDTO.setOrderNo(orderNo);
        Result<String> close = payFeign.close(closeDTO);
        if(close.getCode() != Constants.SUCCESS){
            throw new RuntimeException("调用支付订单关闭失败");
        }
        // 修改订单的状态改为失败
        if(cancelOrderDTO.getSource().equals(OrderSourceEnum.ORDER)){
            new LambdaUpdateChainWrapper<>(danmoOrderMapper).eq(DanmoOrder::getId, cancelOrderDTO.getOrderId())
                    .set(DanmoOrder::getStatus, OrderStatus.CLOSE).update();
        }else {
            danmoOrderMapper.updateMarketOrderById(cancelOrderDTO.getOrderId(), OrderStatus.CLOSE.getCode());
            danmoOrderMapper.updateMarketProductsById(cancelOrderDTO.getOrderId());
        }

    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void updateAddress(UpdateAddressDTO updateAddressDTO) {
        if(updateAddressDTO.getSource().equals(OrderSourceEnum.ORDER)){
            new LambdaUpdateChainWrapper<>(danmoOrderMapper).eq(DanmoOrder::getId, updateAddressDTO.getOrderId())
                    .set(DanmoOrder::getReceiverName, updateAddressDTO.getReceiverName())
                    .set(DanmoOrder::getReceiverPhone, updateAddressDTO.getReceiverPhone())
                    .set(DanmoOrder::getReceiverProvince, updateAddressDTO.getReceiverProvince())
                    .set(DanmoOrder::getReceiverCity, updateAddressDTO.getReceiverCity())
                    .set(DanmoOrder::getReceiverRegion, updateAddressDTO.getReceiverRegion())
                    .set(DanmoOrder::getReceiverDetailAddress, updateAddressDTO.getReceiverDetailAddress())
                    .update();
        }else {
            danmoOrderMapper.updateMarketOrderAddressById(updateAddressDTO);
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void cancelRefund(CancelRefundDTO cancelRefundDTO) {
        // 获取订单信息
        if(cancelRefundDTO.getSource().equals(OrderSourceEnum.ORDER)){
            DanmoOrder danmoOrder = danmoOrderMapper.selectById(cancelRefundDTO.getOrderId());
            if(!danmoOrder.getStatus().equals(OrderStatus.TO_BE_SHIPPED)){
                throw new RuntimeException("订单状态异常");
            }
            danmoOrder.setRefundOrderSn(REFUND_ORDER_TOP + RandomUtil.randomNumbers(16));
            // 生成退款订货单号，进行退款
            RefundDTO refundDTO = new RefundDTO();
            refundDTO.setRefundBizOrderNo(danmoOrder.getRefundOrderSn());
            refundDTO.setOrderNo(danmoOrder.getPayOrderNo());
            Result<RefundResultVO> refund = payFeign.refund(refundDTO);
            if(refund.getCode() != Constants.SUCCESS){
                throw new RuntimeException("调用支付订单退款失败");
            }
            RefundResultVO data = refund.getData();
            if(data.getStatus().equals(PayStatus.FAIL)){
                danmoOrder.setPayRefundOrderNo(data.getRefundOrderNo());
                danmoOrder.setRefundTime(data.getCompletedTime());
                danmoOrder.setStatus(OrderStatus.REFUND_FAILED);
            }else if(data.getStatus().equals(PayStatus.SUCCESS)){
                danmoOrder.setPayRefundOrderNo(data.getRefundOrderNo());
                danmoOrder.setRefundTime(data.getCompletedTime());
                danmoOrder.setStatus(OrderStatus.REFUND_SUCCESS);
            }else {
                danmoOrder.setPayRefundOrderNo(data.getRefundOrderNo());
                danmoOrder.setStatus(OrderStatus.REFUND_PENDING);
            }
            danmoOrderMapper.updateById(danmoOrder);
        }else {
            Integer status = danmoOrderMapper.findMarketOrderStatusByPayId(cancelRefundDTO.getOrderId());
            OrderStatus orderStatus = OrderStatus.getByCode(status);
            if(!orderStatus.equals(OrderStatus.TO_BE_SHIPPED)){
                throw new RuntimeException("订单状态异常");
            }
            String payOrderNo = danmoOrderMapper.findMarketOrderById(cancelRefundDTO.getOrderId());
            String refundOrderSn = REFUND_MARKET_TOP + RandomUtil.randomNumbers(16);
            RefundDTO refundDTO = new RefundDTO();
            refundDTO.setRefundBizOrderNo(refundOrderSn);
            refundDTO.setOrderNo(payOrderNo);
            Result<RefundResultVO> refund = payFeign.refund(refundDTO);
            if(refund.getCode() != Constants.SUCCESS){
                throw new RuntimeException("调用支付订单退款失败");
            }
            RefundResultVO data = refund.getData();
            MarketOrderDTO marketOrderDTO = new MarketOrderDTO();
            marketOrderDTO.setId(cancelRefundDTO.getOrderId());
            marketOrderDTO.setRefundOrderSn(refundOrderSn);
            if(data.getStatus().equals(PayStatus.FAIL)){
                marketOrderDTO.setPayRefundOrderNo(data.getRefundOrderNo());
                marketOrderDTO.setRefundTime(data.getCompletedTime());
                marketOrderDTO.setOrderStatus(OrderStatus.REFUND_FAILED.getCode());
            }else if(data.getStatus().equals(PayStatus.SUCCESS)){
                marketOrderDTO.setPayRefundOrderNo(data.getRefundOrderNo());
                marketOrderDTO.setRefundTime(data.getCompletedTime());
                marketOrderDTO.setOrderStatus(OrderStatus.REFUND_SUCCESS.getCode());
            }else {
                marketOrderDTO.setPayRefundOrderNo(data.getRefundOrderNo());
                marketOrderDTO.setOrderStatus(OrderStatus.REFUND_PENDING.getCode());
            }
            danmoOrderMapper.updateMarketOrderDTO(marketOrderDTO);
            danmoOrderMapper.updateMarketProductsById(cancelRefundDTO.getOrderId());
        }

    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void confirmShipment(ConfirmShipmentDTO confirmShipmentDTO) {
        if(confirmShipmentDTO.getSource().equals(OrderSourceEnum.ORDER)) {
            DanmoOrder danmoOrder = danmoOrderMapper.selectById(confirmShipmentDTO.getOrderId());
            if (!danmoOrder.getStatus().equals(OrderStatus.TO_BE_SHIPPED)) {
                throw new RuntimeException("订单状态异常");
            }
            danmoOrder.setDeliveryCompany(confirmShipmentDTO.getDeliveryCompany());
            danmoOrder.setDeliverySn(confirmShipmentDTO.getDeliverySn());
            danmoOrder.setStatus(OrderStatus.TO_BE_RECEIVED);
            danmoOrder.setDeliveryTime(DateUtil.date());
            danmoOrderMapper.updateById(danmoOrder);
            jPushUtils.send(danmoOrder.getMemberId(), JpushMessageEnum.DELIVERY);
        }else {
            Integer status = danmoOrderMapper.findMarketOrderStatusByPayId(confirmShipmentDTO.getOrderId());
            OrderStatus orderStatus = OrderStatus.getByCode(status);
            if(!orderStatus.equals(OrderStatus.TO_BE_SHIPPED)){
                throw new RuntimeException("订单状态异常");
            }
            MarketOrderDTO marketOrderDTO = new MarketOrderDTO();
            marketOrderDTO.setId(confirmShipmentDTO.getOrderId());
            marketOrderDTO.setOrderStatus(OrderStatus.TO_BE_RECEIVED.getCode());
            marketOrderDTO.setPosExpress(confirmShipmentDTO.getDeliveryCompany());
            marketOrderDTO.setExpressDeliveryNumber(confirmShipmentDTO.getDeliverySn());
            marketOrderDTO.setDeliveryTime(DateUtil.date().toLocalDateTime());
            danmoOrderMapper.updateMarketOrderDTO(marketOrderDTO);
            Long userId = danmoOrderMapper.findUserIdById(confirmShipmentDTO.getOrderId());
            jPushUtils.send(userId, JpushMessageEnum.PAINTING_DELIVERY);
        }
    }

    @Override
    public Object express(ExpressDTO expressDTO) {
        HttpResponse response = HttpRequest.post(url)
                .header("Authorization", "APPCODE " + appCode)
                .header("Content-Type", ContentType.FORM_URLENCODED.getValue())
                .form("expressNo", expressDTO.getDeliverySn())
                .form("mobile", StrUtil.sub(expressDTO.getReceiverPhone(), -4, expressDTO.getReceiverPhone().length()))
                .timeout(5000)
                .execute();
        String body = response.body();
        if(StrUtil.isEmpty(body)){
            throw new RuntimeException("获取不带快递信息");
        }
        JSONObject entries = JSONUtil.parseObj(body);
        return entries.get("data");
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void receiving(ReceivingDTO receivingDTO) {
        if(receivingDTO.getSource().equals(OrderSourceEnum.ORDER)) {
            DanmoOrder danmoOrder = danmoOrderMapper.selectById(receivingDTO.getOrderId());
            if (!danmoOrder.getStatus().equals(OrderStatus.TO_BE_RECEIVED)) {
                throw new RuntimeException("订单状态异常");
            }
            danmoOrder.setStatus(OrderStatus.TO_BE_EVALUATED);
            danmoOrder.setReceiveTime(DateUtil.date());
            danmoOrderMapper.updateById(danmoOrder);
        }else {
            Integer status = danmoOrderMapper.findMarketOrderStatusByPayId(receivingDTO.getOrderId());
            OrderStatus orderStatus = OrderStatus.getByCode(status);
            if (!orderStatus.equals(OrderStatus.TO_BE_RECEIVED)) {
                throw new RuntimeException("订单状态异常");
            }
            MarketOrderDTO marketOrderDTO = new MarketOrderDTO();
            marketOrderDTO.setId(receivingDTO.getOrderId());
            marketOrderDTO.setOrderStatus(OrderStatus.TO_BE_EVALUATED.getCode());
            marketOrderDTO.setTransactionTime(DateUtil.date().toLocalDateTime());
            danmoOrderMapper.updateMarketOrderDTO(marketOrderDTO);
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void evaluation(EvaluationDTO evaluationDTO) {
        if(evaluationDTO.getSource().equals(OrderSourceEnum.ORDER)) {
            DanmoOrder danmoOrder = danmoOrderMapper.selectById(evaluationDTO.getOrderId());
            danmoOrder.setStatus(OrderStatus.SUCCESS);
            danmoOrder.setCommentTime(DateUtil.date());
            danmoOrderMapper.updateById(danmoOrder);
        }else {
//            Integer status = danmoOrderMapper.findMarketOrderStatusByPayId(evaluationDTO.getOrderId());
//            OrderStatus orderStatus = OrderStatus.getByCode(status);
            MarketOrderDTO marketOrderDTO = new MarketOrderDTO();
            marketOrderDTO.setId(evaluationDTO.getOrderId());
            marketOrderDTO.setOrderStatus(OrderStatus.SUCCESS.getCode());
            danmoOrderMapper.updateMarketOrderDTO(marketOrderDTO);
        }
        GoodsEvaluationInfo goodsEvaluationInfo = new GoodsEvaluationInfo();
        BeanUtil.copyProperties(evaluationDTO, goodsEvaluationInfo);
        goodsEvaluationInfo.setCommentsNumber(0);
        goodsEvaluationInfo.setThumbsUp(0);
        Integer score = evaluationDTO.getScore();
        if(score < 3){
            goodsEvaluationInfo.setScoreType(ScoreTypeEnum.BAD);
        }else if(score < 4){
            goodsEvaluationInfo.setScoreType(ScoreTypeEnum.MIDDLE);
        }else {
            goodsEvaluationInfo.setScoreType(ScoreTypeEnum.GOOD);
        }
        goodsEvaluationInfoMapper.insert(goodsEvaluationInfo);

    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void orderStatusConversion() {
        List<DanmoOrder> orders = new LambdaQueryChainWrapper<>(danmoOrderMapper).eq(DanmoOrder::getStatus, OrderStatus.TO_BE_EVALUATED)
                .list();
        orders.forEach(a ->{
            Date receiveTime = a.getReceiveTime();
            DateTime tenDaysLater = DateUtil.offsetDay(receiveTime, 10);
            // 判断是否是今天（只比较日期部分）
            boolean sameDay = DateUtil.isSameDay(tenDaysLater, DateUtil.date());
            if(sameDay){
                a.setStatus(OrderStatus.SUCCESS);
                danmoOrderMapper.updateById(a);
            }
        });
        List<DanmoMarketOrderVO> marketOrder = danmoOrderMapper.findMarketOrder(OrderStatus.TO_BE_EVALUATED.getCode());
        marketOrder.forEach(a ->{
            Date transactionTime = a.getTransactionTime();
            DateTime tenDaysLater = DateUtil.offsetDay(transactionTime, 10);
            // 判断是否是今天（只比较日期部分）
            boolean sameDay = DateUtil.isSameDay(tenDaysLater, DateUtil.date());
            if(sameDay){
                danmoOrderMapper.updateMarketOrderById(a.getId(), OrderStatus.SUCCESS.getCode());
            }
        });
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void deleteOrder(DeleteOrderDTO deleteOrderDTO) {
        if(deleteOrderDTO.getSource().equals(OrderSourceEnum.ORDER)) {
            danmoOrderMapper.deleteById(deleteOrderDTO.getOrderId());
        }else {
            danmoOrderMapper.deleteMarketOrderById(deleteOrderDTO.getOrderId());
        }

    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void closeOrder(CloseOrderDTO closeOrderDTO) {
        // 判断时那个业务的订单
        String bizOrderNo = closeOrderDTO.getOrderSn();
        String top = bizOrderNo.split("_")[0];
        if (StrUtil.isEmpty(top)) {
            return;
        }
        switch (top + "_") {
            case ORDER_TOP:
                danmoOrderMapper.updateOrder(bizOrderNo, OrderStatus.CLOSE.getCode());
                break;
            case MARKET_TOP:
                danmoOrderMapper.updateMarketOrder(bizOrderNo, OrderStatus.CLOSE.getCode());
                break;
            case MEMBER_TOP:
                // 充值业务
                danmoOrderMapper.updateMember(bizOrderNo, PayStatus.FAIL.getCode(),DateUtil.date().toLocalDateTime());
                break;
            case SECURITY_DEPOSIT_TOP:
                PaymentCallBackResult paymentCallBackResult = new PaymentCallBackResult();
                paymentCallBackResult.setBizOrderNo(bizOrderNo);
                paymentCallBackResult.setStatus(PayStatus.FAIL);
                paymentCallBackResult.setCompletedTime(DateUtil.date().toLocalDateTime());
                Result<String> stringResult = securityDepositFegin.payResultsHandle(paymentCallBackResult);
                if (!Result.isSuccess(stringResult)) {
                    log.error(stringResult.getMsg());
                    throw new RuntimeException("处理保证金充值失败！");
                }
                break;
            case PREMIUM_TOP:
                PaymentCallBackResult paymentCallBack = new PaymentCallBackResult();
                paymentCallBack.setBizOrderNo(bizOrderNo);
                paymentCallBack.setStatus(PayStatus.FAIL);
                paymentCallBack.setCompletedTime(DateUtil.date().toLocalDateTime());
                Result<String> result = securityDepositFegin.premiumPayResults(paymentCallBack);
                if (!Result.isSuccess(result)) {
                    log.error(result.getMsg());
                    throw new RuntimeException("处理手续费充值失败！");
                }
                break;
            default:
                throw new RuntimeException("订单业务异常");
        }

    }

}
